# coding = utf-8
import paramiko
import time
import os
import datetime
import redis
import tools
from auto_replace import Replace_settings
from test_setting import  BASE_PATH,JAVA_HOME,PER_RPORT_PATH,ENT_RPORT_PATH,LOG_PATH,WEBAPPS_PATH,BIN_PATH,WORK_PATH,TEMP_PATH,CONF_PATH,HOST_APP,HOST_USER,HOST_PASSWD,HOST_REDIS,REDIS_PORT
class Mytomcat:
    def __init__(self, hostname,  server_port,  username,  password):
        self.hostname = hostname
        self.server_port = server_port
        self.username = username
        self.password = password

# 连接服务器
    def serverconnect(self):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            ssh.connect(hostname=self.hostname, port=self.server_port, username=self.username, password=self.password)
            return ssh
        except Exception as e:
            tools.logger.error('服务器连接失败！%s' % e)
            # raise Exception('服务器连接失败！%s' % e)


# 杀死tomcat进程
    def killtomcat(self,sshconnect):
        tools.logger.info('开始查找tomcat服务')
        # grep -v 反匹配，不匹配-v后面的内容
        # proshell = "ps -ef | grep tomcat | grep -v 'grep' |grep -v '/bin/sh /opt/tomcat/apache-tomcat-8.5.38/bin/catalina.sh start'| awk '{{print $2}}'"# grep -v 反匹配，不匹配-v后面的内容
        proshell = "ps -ef | grep tomcat | grep -v 'grep' |grep '%s'| awk '{{print $2}}'"%BASE_PATH# grep -v 反匹配，不匹配-v后面的内容
        # print(proshell)
        stdin, stdout, stderr = sshconnect.exec_command(proshell)
        pronum = stdout.read().decode('utf-8')  # 转码
        if not pronum:
            tools.logger.info('无启动的tomcat服务！')
        else:
            tools.logger.info('已启动的tomcat为：%s'%pronum)
            sshconnect.exec_command('kill -9 {}'.format(pronum))#杀死进程号
            tools.logger.info('tomcat服务%s已停止！'%pronum)

 # 清空logs目录
    def clearcatalina(self,sshconnect):
        tools.logger.info('开始清空logs目录')
        sshconnect.exec_command('cd %s && rm -rf *'%LOG_PATH)
        tools.logger.info('logs目录已清空')

# 清空work目录的缓存
    def clearwork(self,sshconnect):
        tools.logger.info('开始清空work目录下的Catalina目录')
        sshconnect.exec_command('cd %s && rm -rf Catalina'%WORK_PATH)
        tools.logger.info('work目录下的Catalina目录已删除')

 # 清空conf目录下的Catalina目录
    def clearConfCatalina(self,sshconnect):
        tools.logger.info('开始清空conf目录下的Catalina目录')
        sshconnect.exec_command('cd %s && rm -rf Catalina'%CONF_PATH)
        tools.logger.info('conf目录下的Catalina目录已清除')

# 清空temp目录缓存
    def cleartemp(self,sshconnect):
        tools.logger.info('开始清空temp目录')
        sshconnect.exec_command('cd %s && rm -rf *'%TEMP_PATH)
        tools.logger.info('temp目录已清空')

 # 清空落地报告
    def clearReport(self,sshconnect):
        # cur_time = time.strftime('%y-%m-%d %X')
        tools.logger.info('开始清空落地报告')
        sshconnect.exec_command('cd %s && rm -rf *'%PER_RPORT_PATH)#个人落地报告路径
        sshconnect.exec_command('cd %s && rm -rf *'%ENT_RPORT_PATH)#企业落地报告路径
        tools.logger.info('落地报告已清空')

    # 清redis
    def clearredis(self,host,port):
        # cur_time = time.strftime('%y-%m-%d %X')
        tools.logger.info('开始清空redis')
        try:
            r = redis.Redis(host=host, port=port, decode_responses=True)
        except Exception as e:
            tools.logger.error('redis连接失败，报错%s'%e)
        else:
            r.flushall()
            r.close()
            tools.logger.info('redis已清空')

    #清理webapps中的旧包
    def rm_oldfile(self,sshconnect):
        stdin, stdout, stderr = sshconnect.exec_command('cd {};ls'.format(WEBAPPS_PATH))
        file_list = stdout.read().decode('utf-8')
        tools.logger.info('上传新包前AP服务器{}目录下文件:【\n{}】'.format(WEBAPPS_PATH, file_list))
        old_war_list = file_list.split('\n')
        old_war_list.pop(-1)
        tools.logger.info('old_war_list:{}', old_war_list)
        local_war_list,file_path_list = tools.find_wars()
        for war in local_war_list:
            if war in old_war_list:
                sshconnect.exec_command('rm -rf {}{}'.format(WEBAPPS_PATH, war))
                tools.logger.info('服务器{}已删除'.format(war))
                war = war+'.war'
                sshconnect.exec_command('rm -rf {}{}'.format(WEBAPPS_PATH, war))
                tools.logger.info('服务器{}已删除'.format(war))

    # 上传文件 war
    def upload_all_wars(self,sshconnect):
        t = paramiko.Transport(self.hostname, self.server_port)
        t.connect(username=self.username, password=self.password)
        p = paramiko.SFTPClient.from_transport(t)  # sftp传输
        local_war_list, file_path_list = tools.find_wars()
        if local_war_list!='a':
            for local_war in file_path_list:
                tools.logger.info('{}开始上传'.format(local_war))
                war_index = file_path_list.index(local_war)
                war = local_war_list[war_index]+'.war'
                remote_war = os.path.join(WEBAPPS_PATH,war)
                p.put(local_war, remote_war)
                tools.logger.info('{}已上传至AP服务器'.format(war))
        else:
            tools.logger.info('没有文件需要上传')

   #上传解压过的文件夹
    def upload(self,local_dir, remote_dir):
        all_file = os.listdir(local_dir)
        if all_file:
            try:
                t = paramiko.Transport(self.hostname, self.server_port)
                t.connect(username=self.username, password=self.password)
                sftp = paramiko.SFTPClient.from_transport(t)
                tools.logger.info('upload file start！')
                for root, dirs, files in os.walk(local_dir):
                    for filespath in files:
                        if '.war' not in filespath:
                            local_file = os.path.join(root, filespath)
                            a=local_file.replace('\\','/')
                            a = a.replace(local_dir, '')
                            remote_file = os.path.join(remote_dir, a)
                            try:
                                sftp.put(local_file, remote_file)
                            except Exception as e:
                                sftp.mkdir(os.path.split(remote_file)[0])
                                sftp.put(local_file, remote_file)
                            tools.logger.info("upload %s to remote %s" % (local_file, remote_file))
                    for name in dirs:
                        local_path = os.path.join(root, name)
                        a = local_path.replace('\\', '/')
                        a = a.replace(local_dir, '')
                        remote_path = os.path.join(remote_dir, a)
                        try:
                            sftp.mkdir(remote_path)
                            tools.logger.info("mkdir path %s" % remote_path)
                        except Exception as e:
                            tools.logger.error('报错',e)
                tools.logger.info('upload file success %s ' % datetime.datetime.now())
                t.close()
                # else:
                #     print('本地目录%s为空，无文件可上传！'%local_dir)
            except Exception as e:
                tools.logger.error('报错',e)
        else:
            tools.logger.error('本地目录%s为空'%local_dir)

# 启动tomcat
    def starttomcat(self,sshconnect):
        tools.logger.info('开始启动tomcat')
        #启动命令
        # sshconnect.exec_command('export JAVA_HOME=%s;sh %s/startup.sh'%(BIN_PATH,JAVA_HOME))
        sshconnect.exec_command('export JAVA_HOME=%s;sh %s/startup.sh'%(JAVA_HOME,BIN_PATH))
        time.sleep(2)
        #获取启动成功后的pid
        proshell = "ps -ef | grep tomcat| grep -v 'grep' |grep '%s'| awk '{{print $2}}'"%BASE_PATH
        # grep -v 反匹配，不匹配-v后面的内容
        # awk '{print $2}' 一行一行的读取指定的文件， 以空格作为分隔符，打印第二个字段
        stdin, stdout, stderr = sshconnect.exec_command(proshell)
        # stdin, stdout, stderr = ssh.exec_command('date')#执行命令并获取命令结果
        #stdin为输入的命令
        #stdout为命令返回的结果
        #stderr为命令错误时返回的结果
        pronum = stdout.read().decode('utf-8')
        if not pronum:
            tools.logger.error('启动失败')
        else:
            tools.logger.info('tomcat正在启动，请稍等，进程号是%s,请去服务器%s上%s目录下查看启动日志！\n2分钟后执行ls |grep "Server startup" catalina.out可查看是否启动成功'%(pronum,HOST_APP,LOG_PATH))
    def check_start(self,sshconnect):
        stdin, stdout, stderr = sshconnect.exec_command('cd %s;ls |grep "Server startup" catalina.out' % LOG_PATH)
        res = stdout.read().decode('utf-8')
        if res:
            tools.logger.info('已启动成功！返回:%s'%res)
        else:
            tools.logger.error('未启动成功！')


    def close(self,sshconnect):
        sshconnect.close()

    def auto_run(self):
        sshconnect = self.serverconnect()
        self.killtomcat(sshconnect)  # 杀死原有服务
        # 清空tomcat相关垃圾数据
        self.clearcatalina(sshconnect)
        self.clearConfCatalina(sshconnect)
        self.clearwork(sshconnect)
        self.cleartemp(sshconnect)
        # myTomcat.clearReport() #平时不删除落地报告，压测时需要
        self.clearredis(HOST_REDIS, REDIS_PORT)  # 清空redis
        #!!! 删服务器上的旧包
        self.rm_oldfile(sshconnect)
        #上传新war包
        self.upload_all_wars(sshconnect)
        self.starttomcat(sshconnect)  # 启动服务
        self.close(sshconnect)
        time.sleep(3)
        Replace_settings.del_local_files()

if __name__ == '__main__':
    myTomcat = Mytomcat(HOST_APP, 22, HOST_USER, HOST_PASSWD)  # 测试服务
    myTomcat.auto_run()

